/***2023-02-07 迷途小羔羊
 * 用于编写运动物体的物体类
 * 
*/
namespace ghost {
	export class DriftObj extends ObjBase{
		public _attackTarX:number;
		public _attackTarY:number;
		/**弹道击打目标记录*/private _hitDict:{[id:number]:number};		
		/**穿透数量，默认NaN全穿透*/public penatrateNum:number;
		/**飞行耗费时间*/public _flyUseTime:number;
		/**弹道类型*/public _ballisticType:number;
		/**弹道参数*/public _ballisticParams:number[];
		/**是否无目标发射*/protected _hasTarget:boolean;
		/**计算后的飞行目标X*/public _flyToX:number;
		/**计算后的飞行目标Y*/public _flyToY:number;
		/**计算后的飞行目标H*/public _flyToH:number;
		/**计算后的飞行目标角度*/public _flyToAngle:number;
		/**是否aoe物体*/public _isAOE:boolean;
		/**同一个角色的击打次数上限，默认0，不限制*/protected _hitLimit:number;
		// public _target:GameRole;
		// protected _targetId:number;
		protected _reachDisappear:boolean;
		public _attackTarH:number;
		protected _flySpeed:number;
		/**是否仅攻击目标*/protected _justTarget:number;
		/**子弹飞行进度百分比*/public _flyPercent:number;		
		public constructor(sceneMgr:SceneManager=null) {
			super(sceneMgr);
			let s= this;
			// s._skin.enabledDebugDraw = true;			
			// s._skin.debugMaxAtk = false;
			// s._skin.debugTerritory = false;
		}		
		public exitLoop(t: number, index: number): void 
		{
			let s = this;			
			super.exitLoop(t, index);			
			if (s._sts >= StsType.ATTACK) {
				s.attacking();
			}			
		}
		public worldPosSet():void
		{
			let s= this;
			if(s.isSceneLayer())
			{				
				s._skin.x = s._absX - s._scene.mapX;					
				s._skin.y = s._absY - s._absZ - s._scene.mapY - s._floatH;					
				
			}				
			else
			{				
				s._skin.x = s._owner._scaleDir == map2D.DirectionType.RIGHT?-s._absX:s._absX;
				s._skin.y = s._absY - s._absZ - s._floatH;					
			}			
		}   
		protected init():void
		{
			super.init();
			let s= this;
			s.moveTimeTicker = new map2D.TimeTicker(s._scene);			
		}		
		protected attacking(): boolean {
			let s = this;
			let hitRange:number[],range:number[];
			let role:GameRole;
			let ox:number,oy:number,absX:number,absY:number;				
			let len:number,j:number,len2:number;
			let arr:GameRole[];
			let aRange:number[] = [];	
			let skillCfg:SkillCfg;
			range = s._skinPart.hitRange;
			skillCfg = s._ownerData._skillData.skillCfg;		
			let o:Role;
			o = s.getOwner();
			if(s._layerType >= map2D.LayerType.ROLE_BACK)
			{
				absX = o.absX;
				absY = o.absY;
			}
			else
			{
				absX = s._absX;
				absY = s._absY;
			}
			let isRoleLayer:boolean = !s.isSceneLayer();
			ox = (isRoleLayer?s.skin.x:0);
			oy = (isRoleLayer?s.skin.y:0);
			//计算攻击帧范围								
			let m:Laya.Matrix;
			let agl:number;					
			
			aRange.length = 0;								
			if(s._autoRotate)
			{
				agl = s._autoRotation*MathUtil.DEG_TO_RAD;
				m = Laya.Matrix.TEMP;
				m.identity();
				m.rotate(agl);
				len2 = range.length;
				for(j=0;j<len2;j+=2)
				{
					aRange[j] = absX + m.a * range[j] + m.c * range[j+1];
					aRange[j+1] = absY + m.d * range[j+1] + m.b * range[j];
				}
			}
			else 
			{
				len2 = range.length;
				for(j=0;j<len2;j+=2)
				{
					aRange[j] = ox + absX + (s._dirScaleX > 0?-range[j]:range[j])|0;
					aRange[j+1] = oy + absY + (range[j+1]|0);
				}		
			}	
			let count:number = skillCfg.skillTarget?skillCfg.skillTarget:Number.MAX_VALUE;
			let hitFlag:boolean=false;
			arr = s.findEnemy(s._ownerData._skillData);
			len = arr.length;
			while(--len>-1)
			{
				role = arr[len];					
				hitRange = role.getBodyRange(role.direction);	
				if(PositionUtil.isShapeInsert(aRange, hitRange))
				{					
					s.addHitToTarget(role);					
					hitFlag = true;
					--count;
					if(count <= 0)					
						break;
				}
			}
			if(hitFlag)
				s.resetSts();
			return hitFlag;
		}		
		public addHitToTarget(target:GameRole):boolean
		{
			let s = this;			
			if(s.addHitCount(target))
				return super.addHitToTarget(target);
			return false;
		}		
		/**记录击中次数，添加次数成功返回true*/
		protected addHitCount(target:GameRole):boolean
		{
			let s = this;
			if(s.penatrateNum == 0)//穿透数量限制
				return false;
			if(s._hitDict[target._id] >= s._hitLimit)//弹道针对同一个角色只击打一次
				return false;			
			if(s._hitDict[target._id] == null)//穿透击中新目标
			{				
				s._hitDict[target._id] = 1;
				--s.penatrateNum;
			}				
			else
				++s._hitDict[target._id];
			return true;
		}
		public inArea():void
		{
			//物体不参与占地碰撞
			// let s= this;
			// s.col = Math.floor(s._absX / s._scene.sceneLogic._posGridW);
            // s.row = Math.floor(s._absY / s._scene.sceneLogic._posGridH);
		}		
		public setConfig(cfg:any):void
		{			
			super.setConfig(cfg);
			let s= this;
			s._shootH = cfg.shootH?cfg.shootH:0;			
		}				
		public setSts(sts:number=0,direction:number=-1):void
		{
			super.setSts(sts, direction);
			// let s = this;
			// s._attackFrameIndex = s._skinPart.curRate;			
		}	
		protected resetingSts():void
		{			
			let s= this;
			if(s._justTarget == 1 && s._targetMove && s.targetIsValid())//锁定目标的子弹只在飞行停止时消失
				return;			
			if(s._clothesConfig[StsType.DEATH])
				s.setSts(StsType.DEATH);
			else
				s.del();
		}
		public del():boolean
		{
			return super.del();
		}
		/**是否抛射轨迹*/
		private isObliqueType():boolean
		{
			return this._ballisticType == BallisticType.OBLIQUE || this._ballisticType == BallisticType.FOLLOW_OBLIQUE;
		}
		/**是否跟踪*/
		private isFollowType():boolean
		{
			return this._ballisticType == BallisticType.FOLLOW || this._ballisticType == BallisticType.FOLLOW_OBLIQUE;
		}
		/**设置飞行时间*/
		public setFlyUserTime(flySpeed:number, notRotate:number=0):void
		{
			let s= this;
			s._flySpeed = flySpeed;			
			s._isAOE = s._flySpeed == 0;
			s._autoRotate = notRotate == 0 && flySpeed != 0;
			if(s._isAOE)				
				s.changeSmart(null);			
		}
		/**重新计算飞行总时长
		 * @param calibration 是否逐步校准的方式定位，逐步校准则需要多次计算靠近目标，默认false
		 * **/
		public resetFlyTime(calibration:boolean=false):void
		{
			let s =  this;
			let dis:number;
			s._targetDis = dis = s._reachDisappear?PositionUtil.calculateDistance(s._attackTarX, s._attackTarY, s._absX, s._absY):DriftObj.MAX_DIS;
			let flySpeed:number = (calibration?2:1) * s._flySpeed;
			s._flyUseTime = flySpeed == 0?0:Math.max(CommonUtil.delta*2, dis / flySpeed * 1000);
		}
		/**同一个角色的击打次数上限，默认0，不限制*/
		public setHitLitmit(val:number):void
		{
			let s= this;
			s._hitLimit = val==0?Number.MAX_VALUE:(val|0);
		}
		/**设置弹道类型参数*/
		public setBalistic(params:number[])
		{
			let s = this;			
			s._ballisticType = params?params[0]:BallisticType.COMMON;
			s._ballisticParams = params;
			if(s._ballisticType == BallisticType.OBLIQUE)			
				s._shootH = params[1] > 0?params[1]:100;
			else if(s.isFollowType())
			{
				s._justTarget = params[1] > 0?params[1]:0;			
				if(s._ballisticType == BallisticType.FOLLOW_OBLIQUE)
					s._shootH = params[2] > 0?params[2]:100;
			}
		}		
		/**设置攻击目标位置
		 * @param x
		 * @param y
		 * @param reachDisappear 是否到达目标就消失
		 * @param floatH 目标高度
		*/
		public setAttackTarPos(x:number,y:number, reachDisappear:boolean=true, floatH:number=NaN, target:GameRole=null):void
		{
			let s = this;
			s._flyPercent = NaN;
			s._attackTarX = x;
			s._attackTarY = y;			
			s._attackTarH = floatH;
			s._flyToH = floatH;
			s._targetRoles[0] = target;
			s._targetIds[0] = target?target._id:NaN;
			s._reachDisappear = s.isObliqueType() || reachDisappear;
			s.resetTargetPos();
			s.worldPosSet();
		}			
		/**重新定位目标坐标
		 * @param calibration 是否逐步校准的方式定位，逐步校准则需要多次计算靠近目标，默认false
		 * **/
		public resetTargetPos(calibration:boolean=false):void
		{
			let s = this;
			let angle:number;						
			if(s.targetIsValid())
			{				
				let tx:number, ty:number;
				tx = s._targetRoles[0].absX;
				ty = s._targetRoles[0].absY;
				if(calibration && PositionUtil.calculateDistance(s._attackTarX, s._attackTarY, tx, ty) > 10)
				{
					let pt:Laya.Point;					
					pt = MathUtil.calLinePoint(s._attackTarX, s._attackTarY, tx, ty, 10);
					s._attackTarX = pt.x;
					s._attackTarY = pt.y;					
				}
				else
				{
					s._attackTarX = tx;
					s._attackTarY = ty;
				}
				
			}
			//上面得到目标坐标，则可以计算用时
			s.resetFlyTime(calibration);	
			if(s._autoRotate)
			{				
				s._hasTarget = s._attackTarX == s._attackTarX && s._attackTarY == s._attackTarY;
				let per:number;
				if(s._hasTarget && s._attackTarH == s._attackTarH)
				{
					per = s._targetDis / PositionUtil.calculateDistance(s._absX, s._absY, s._attackTarX, s._attackTarY);					
					s._flyToH = s._floatH - (s._floatH - s._attackTarH) * per;					
				}
				else
					s._flyToH = NaN;					
				if(s._hasTarget && s._reachDisappear)
				{					
					s._flyToX = s._attackTarX;
					s._flyToY = s._attackTarY;
				}
				else
				{					
					if(s._hasTarget)
						angle = PositionUtil.calculateAngle(s._attackTarX, s._attackTarY, s._absX, s._absY);
					else
						angle = map2D.DirectionType.getDirectorAngle(s._createDir);
					s._flyToX = s._absX + s._targetDis*Math.cos(angle);
					s._flyToY = s._absY + s._targetDis*Math.sin(angle);
				}				
				s.setRotation(s.calAutoRotation(s._absX, s._absY, s._flyToX, s._flyToY - s._attackTarH));
			}
			else
			{
				s._flyToX = s._attackTarX;
				s._flyToY = s._attackTarY;
				s._flyToH = s._attackTarH;
			}				
		}			
		protected moveSmartEnd():void
		{
			let s= this;
			if(!s._hasTargetPos)
			{
				// s.attacking();				
				if(s._flySpeed > 0)
					s.resetSts();
				s.moveFlagSet(false);
				if(s._moveEndCall!=null)
				{
					let func:Function,obj:any;
					func = s._moveEndCall;
					obj = s._moveEndObj;
					s._moveEndObj = s._moveEndCall = null;
					func.call(obj);
				}				
			}						
		}		
		public moveTo(abX:number,abY:number,callBack:Function=null,thisObj:any=null,sts:number=NaN,time:number=500,dir:number=-1, floatH:number=NaN):void
		{			
			let s = this;			
			if(s._attackTarX != s._attackTarX || s._attackTarY != s._attackTarY)
			{				
				return;
			}
			if(s._flyPercent != s._flyPercent)
				s._flyPercent = 0;
			else if(s.moveTimeTicker.running())
				s._flyPercent += (1 - s._flyPercent) * s.moveTimeTicker.getPercent();//记录进度			
			let agl:number,disX:number,disY:number;		
			sts = sts == sts?sts:StsType.STAND;
			s._dirMove = false;
			s.moveFlagSet(true);			
			disX = abX - s._absX;
			disY = abY - s._absY;			
			if(sts > -1)
			{
				if(dir == -1)
				{
					agl = Math.atan2(disY,disX);
					dir = map2D.DirectionType.getDirectorSts(agl)
				}
				s.setSts(sts, dir);
			}				
			disX = Math.pow(disX*disX + disY*disY,0.5);
			s.moveTimeTicker.init(s._scene.timeTick,time);			
			s._speedH = s._speedY = s._speedX = 0;//按时间走，速度改成百分比距离			
			s._targetX = abX;
			s._targetY = abY;
			s._targetH = floatH;
			if(s._autoRotate)
			{	
				s.setRotation(s.calAutoRotation(s._absX,s._absY,s._targetX,s._targetY));				
			}
				
			s._hasTargetPos  = s._targetX == s._targetX || s._targetY == s._targetY || s._targetH == s._targetH;			
			s._moveEndCall = callBack;
			s._moveEndObj = thisObj;			
		}		
		
		/**重设针对目标的行走方向*/
		public resetTargetDir(target:Role,angleOffet:number=0):void
		{
			let s= this;
			let tarAngle:number;			
			tarAngle = PositionUtil.calculateAngle(target.absX,target.absY,s._absX,s._absY) + angleOffet;												
			s._targetAngle = tarAngle;
			s._targetDirection = map2D.DirectionType.getDirectorSts(tarAngle);
		}

		public outPoolInit():void
		{
			super.outPoolInit();
			let s= this;
			s._flyToX = s._flyToY = s._attackTarX = s._attackTarY = NaN;
			s._hitLimit = 0;
			s._targetDis = DriftObj.MAX_DIS;			
			s.penatrateNum = NaN;
			s._flyUseTime = 100;
			s._hasTarget = false;
			s._hitDict = {};						
		}
		public beforeToPool():void
		{
			super.beforeToPool();
			let s = this;
			s._hitDict = null;
		}

		private _targetDis:number;
		public _shootH:number;			
		public static MAX_DIS:number = 1200;
	}
}